package com.baseproject.datasource.get.procedure;

import com.baseproject.datasource.get.request.params.LocalRequestParams;
import com.baseproject.datasource.get.request.params.RemoteRequestParams;
import com.baseproject.datasource.get.request.type.ObjectRequestType;
import com.baseproject.datasource.get.request.type.RequestType;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import rx.Observable;
import rx.Scheduler;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * 1 数据获取方式
 * 1.1正常流程
 * 1.2 优先网络流程
 * 1.3 localOnly
 * 1.4 RemoteOnly
 */
public abstract class DataProcedure {

    /**
     * 是否需要将网络返回结果保存到本地
     */
    protected boolean ifNeedSaveToLocal = true;
    protected boolean ifShowProgressDialog = true;

    protected LocalRequestParams mLocalRequestParams;
    protected RemoteRequestParams mRemoteRequestParams;

    protected RequestType mRequestType = new ObjectRequestType();

    protected Scheduler subscribeOn = Schedulers.io();
    protected Scheduler observeOn = AndroidSchedulers.mainThread();

    protected Class className;

    public abstract <T> Observable<List<T>> getList(Class<T> className);

    protected DataProcedure(Class className) {
        this.className = className;
    }

    public static DataProcedure createRemoteFirst(Class className) {
        return new RemoteFirstDataProcedure(className);
    }

    public static DataProcedure createCommon(Class className) {
        return new CommonDataProcedure(className);
    }

    public static DataProcedure createCommonRemote(Class className) {
        return new CommonRemoteDataProcedure(className);
    }

    public static DataProcedure createLocalOnly(Class className) {
        return new LocalOnlyDataProcedure(className);
    }

    public static DataProcedure createRemoteOnly(Class className) {
        return new RemoteOnlyDataProcedure(className);
    }

    public DataProcedure setLocalRequestParams(String uniqueKey) {
        if (null == mLocalRequestParams) {
            mLocalRequestParams = new LocalRequestParams(uniqueKey);
        } else {
            mLocalRequestParams.setUniqueKey(uniqueKey);
        }
        return this;
    }

    public DataProcedure setRemoteRequestParams(String uniqueKey, String url) {
        if (null == mRemoteRequestParams) {
            mRemoteRequestParams = new RemoteRequestParams(uniqueKey, url);
        } else {
            mRemoteRequestParams.setUniqueKey(uniqueKey);
            mRemoteRequestParams.setUrl(url);
        }
        return this;
    }

    public DataProcedure setRequestParams(String uniqueKey, String url) {
        setLocalRequestParams(uniqueKey);
        setRemoteRequestParams(uniqueKey, url);
        return this;
    }

    //////////////////////local start /////////////////////////////////////
    public Map<String, String> getWhere() {
        return null != mLocalRequestParams ? mLocalRequestParams.getWhere() : null;
    }

    public DataProcedure setWhere(Map<String, String> where) {
        ensureLocalRequestParams();
        mLocalRequestParams.setWhere(where);
        return this;
    }

    public String[] getProjections() {
        return null != mLocalRequestParams? mLocalRequestParams.getProjections(): null;
    }

    public DataProcedure setProjections(String[] projections) {
        ensureLocalRequestParams();
        mLocalRequestParams.setProjections(projections);
        return this;
    }

    private void ensureLocalRequestParams() {
        if (null == mLocalRequestParams) {
            mLocalRequestParams = new LocalRequestParams();
        }
    }

    //////////////////////////local end/////////////////////////////


    ////////////////////////////remote start///////////////////////////

    public HashMap<String, String> getHeaderParams() {
        return null != mRemoteRequestParams ? mRemoteRequestParams.getHeaderParams() : null;
    }

    public DataProcedure setHeaderParams(HashMap<String, String> headerParams) {
        ensureRemoteRequestParams();
        mRemoteRequestParams.setHeaderParams(headerParams);
        return this;
    }

    public Map<String, String> getQueryParams() {
        return null != mRemoteRequestParams ? mRemoteRequestParams.getQueryParams() : null;
    }

    public DataProcedure setQueryParams(Map<String, String> queryParams) {
        ensureRemoteRequestParams();
        mRemoteRequestParams.setQueryParams(queryParams);
        return this;
    }

    private void ensureRemoteRequestParams() {
        if (null == mRemoteRequestParams) {
            mRemoteRequestParams = new RemoteRequestParams();
        }
    }

    //////////////////////////remote end ///////////////////////////////


    public Class getClassName() {
        return className;
    }

    public String getUniqueKey() {
        if (null != mLocalRequestParams) {
            return mLocalRequestParams.getUniqueKey();
        }
        if (null != mRemoteRequestParams) {
            return mRemoteRequestParams.getUniqueKey();
        }
        return null;
    }

    public boolean isIfNeedSaveToLocal() {
        return ifNeedSaveToLocal;
    }

    public DataProcedure setIfNeedSaveToLocal(boolean ifNeedSaveToLocal) {
        this.ifNeedSaveToLocal = ifNeedSaveToLocal;
        return this;
    }

    public boolean isIfShowProgressDialog() {
        return ifShowProgressDialog;
    }

    public DataProcedure setIfShowProgressDialog(boolean ifShowProgressDialog) {
        this.ifShowProgressDialog = ifShowProgressDialog;
        return this;
    }

    public RequestType getRequestType() {
        return mRequestType;
    }

    public DataProcedure setRequestType(RequestType mRequestType) {
        this.mRequestType = mRequestType;
        return this;
    }

    public LocalRequestParams getLocalRequestParams() {
        return mLocalRequestParams;
    }

    public DataProcedure setLocalRequestParams(LocalRequestParams mLocalRequestParams) {
        this.mLocalRequestParams = mLocalRequestParams;
        return this;
    }

    public RemoteRequestParams getRemoteRequestParams() {
        return mRemoteRequestParams;
    }

    public DataProcedure setRemoteRequestParams(RemoteRequestParams mRemoteRequestParams) {
        this.mRemoteRequestParams = mRemoteRequestParams;
        return this;
    }

    public Scheduler getSubscribeOn() {
        return subscribeOn;
    }

    public DataProcedure setSubscribeOn(Scheduler subscribeOn) {
        this.subscribeOn = subscribeOn;
        return this;
    }

    public Scheduler getObserveOn() {
        return observeOn;
    }

    public DataProcedure setObserveOn(Scheduler observeOn) {
        this.observeOn = observeOn;
        return this;
    }
}
